import JJService from '../JJService.js'
import JJLoginRequest from './network/JJLoginRequest.js'
import { JJCrypt, JJUtil, JJLog } from "../../util/index.js";
import { JJError, JJHttpHelper, JJReportMonitorHelper } from '../../bizUtil/index.js'
import { hexMD5, WxNotificationCenter } from '../../thirdparty/index.js'

export default class JJLoginService {

    /******* Identity *******/
    // 登录微信服务器
    static JJLoginServiceIdentityWechatLogin = 'JJLoginService_wechatLogin'
    // 密码登录
    static JJLoginServiceIdentityPasswordLogin = 'JJLoginService_PasswordLogin'
    // 免密登录
    static JJLoginServiceIdentityNoPasswordLogin = 'JJLoginService_NoPasswordLogin'
    // 检查是否已注册
    static JJLoginServiceIdentityCheckRegister = "JJLoginService_checkRegister";
    // 注册
    static JJLoginServiceIdentityRegister = 'JJLoginService_Register'
    // 获取密钥
    static JJLoginServiceIdentityGetSecretkey = 'JJLoginService_getSecretkey'
    // 获取微信用户信息
    static JJLoginServiceIdentityGetWechatUserInfo = 'JJLoginService_getWechatUserInfo'
    // 退出登录
    static JJLoginServiceIdentityLogout = 'JJLoginService_logout'
    // open id
    static JJLoginServiceIdentityOpenID = 'JJLoginService_openID'
    // union id
    static JJLoginServiceIdentityUnionID = 'JJLoginService_unionID'
    // 上一次登录用户信息
    static JJLoginServiceIdentityLastLoginInfo = 'JJLoginService_LastLoginInfo'

    /******* Notification *******/
    // 登录成功
    static JJLoginServiceNotificationNameLoginSuccess = 'JJLoginServiceNotificationNameLoginSuccess'
    // 退出登录成功
    static JJLoginServiceNotificationNameLogoutSuccess = 'JJLoginServiceNotificationNameLogoutSuccess'
    // 登录session超时
    static JJLoginServiceNotificationNameLoginSessionTimeout = 'JJLoginServiceNotificationNameLoginSessionTimeout'

    static instance
    static shareInstance() {
        if (false === this.instance instanceof this) {
            this.instance = new this
        }
        return this.instance
    }

    // !! use getXXX setXXX function to get or set value, such as: getLoginInfo() ...
    // 微信账户相关
    openID = null
    unionID = null
    wechatUserInfo = null

    // app账户相关
    sessionKey = null
    loginInfo = null
    userID = null
    isUserDidOnline = false
    secretkey = null

    getOpenID() {
        if (JJUtil.isNotNull(this.openID) && this.openID.length > 0) {
            return this.openID
        }

        const openID = JJService.customCacheObject(JJLoginService.JJLoginServiceIdentityOpenID)
        if (JJUtil.isNotNull(openID) && openID.length > 0) {
            this.openID = openID
        }

        return this.openID
    }

    setOpenID(_openID) {
        if (JJUtil.isNotNull(_openID) && _openID.length > 0){
            this.openID = _openID
            JJService.saveCustomCacheObject(_openID, JJLoginService.JJLoginServiceIdentityOpenID)
        }
    }

    getUnionID() {
        if (JJUtil.isNotNull(this.unionID) && this.unionID.length > 0) {
            return this.unionID
        }

        const unionID = JJService.customCacheObject(JJLoginService.JJLoginServiceIdentityUnionID)
        if (JJUtil.isNotNull(unionID) && unionID.length > 0) {
            this.unionID = unionID
        }

        return this.unionID
    }

    setUnionID(_unionID) {
        if (JJUtil.isNotNull(_unionID) && _unionID.length > 0) {
            this.unionID = _unionID
            JJService.saveCustomCacheObject(_unionID, JJLoginService.JJLoginServiceIdentityUnionID)
        }
    }

    getWechatUserInfo() {
        return this.wechatUserInfo
    }

    setWechatUserInfo(_wechatUserInfo) {
        this.wechatUserInfo = _wechatUserInfo
    }

    getSessionKey() {
        return this.sessionKey
    }

    setSessionKey(_sessionKey) {
        this.sessionKey = _sessionKey
    }

    getLoginInfo() {
        if (JJUtil.isNotNull(this.loginInfo)) {
            return this.loginInfo
        }

        const lastLoginInfo = JJService.customCacheObject(JJLoginService.JJLoginServiceIdentityLastLoginInfo)
        if (!JJUtil.isEmpty(lastLoginInfo)) {
            this.loginInfo = lastLoginInfo
        }
        
        return this.loginInfo
    }

    setLoginInfo(_loginInfo) {
        this.loginInfo = _loginInfo

        if (JJUtil.isNull(this.loginInfo)) {
            JJService.removeCustomCacheObject(JJLoginService.JJLoginServiceIdentityLastLoginInfo)
        } else {
            JJService.saveCustomCacheObject(this.loginInfo, JJLoginService.JJLoginServiceIdentityLastLoginInfo)
        }
    }

    getUserID() {
        return this.userID
    }

    setUserID(_userID) {
        this.userID = _userID
    }

    getIsUserDidOnline() {
        return this.isUserDidOnline
    }

    setIsUserDidOnline(_isUserDidOnline) {
        this.isUserDidOnline = _isUserDidOnline
    }

    getSecretkey() {
        // todo 如果业务没有首先获取密钥的需求，直接返回任何非null数据
        return "no secret key"
        //return this.secretkey
    }

    setSecretkey(_secretkey) {
        this.secretkey = _secretkey
    }
    
    clear() {
        this.setSessionKey(null)
        this.setLoginInfo(null)
        this.setUserID(null)
    }

    // 密码登录
    requestPasswordLogin(params, networkSuccessCallBack, networkFailCallBack) {
        this.__requestLogin(params, JJLoginService.JJLoginServiceIdentityPasswordLogin, networkSuccessCallBack, networkFailCallBack)
    }

    // 是否已注册
    requestCheckRegister(param, networkSuccessCallBack, networkFailCallBack, cacheCallBack) {
        JJService.request(JJLoginRequest, JJLoginService.JJLoginServiceIdentityCheckRegister, param, true, false, networkSuccessCallBack, networkFailCallBack, cacheCallBack);
    }
    
    // 注册
    requestRegister(params, networkSuccessCallBack, networkFailCallBack) {
        this.__requestLogin(params, JJLoginService.JJLoginServiceIdentityRegister, networkSuccessCallBack, networkFailCallBack)
    }

    isNeedNoPasswordLogin() {
        if (this.getIsUserDidOnline()) {
            return Promise.resolve({ isNeed: false })
        }

        let lastLoginInfo = JJService.customCacheObject(JJLoginService.JJLoginServiceIdentityLastLoginInfo) 
        if (JJUtil.isEmpty(lastLoginInfo)) {
            lastLoginInfo = this.getLoginInfo()
        }

        if (JJUtil.isNotNull(lastLoginInfo)) {
            return Promise.resolve({ isNeed: true } )
        } else {
            return Promise.resolve({ isNeed: false })
        }
    }

    isNoPasswordLoginDoing = false
    // 免密登录
    requestNoPasswordLogin(params, networkSuccessCallBack, networkFailCallBack) {
        if (this.isNoPasswordLoginDoing) {
            return
        }

        this.isNoPasswordLoginDoing = true
        let me = this
        this.__requestLogin(params, JJLoginService.JJLoginServiceIdentityNoPasswordLogin, function (isSuccess, value, otherInfo) {
            me.isNoPasswordLoginDoing = false
            networkSuccessCallBack(isSuccess, value, otherInfo)
        }, function (error, otherInfo) {
            me.isNoPasswordLoginDoing = false
            networkFailCallBack(error, otherInfo)
        })
    }

    isGetSecretkeyDoing = false
    // 获取密钥
    requestGetSecretkey(networkSuccessCallBack, networkFailCallBack) {
        if (this.isGetSecretkeyDoing) {
            return;
        }

        this.isGetSecretkeyDoing = true
        
        // todo set parameter
        let parameter = {}

        const request = new JJLoginRequest(JJLoginService.JJLoginServiceIdentityGetSecretkey, parameter, false, false);
        const me = this;
        request.start(function (isSuccess, value, otherInfo) {
            me.isGetSecretkeyDoing = false
            if (isSuccess) {
                // todo save secret key
                me.setSecretkey(value)
            }
            networkSuccessCallBack(isSuccess, value, otherInfo)
        }, function (error, otherInfo) {
            me.isGetSecretkeyDoing = false
            networkFailCallBack(error, otherInfo)
        })
    }

    // 微信用户信息
    requestWechatUserInfo(isCredentials, networkSuccessCallBack, networkFailCallBack) {
        if (!isCredentials || JJUtil.isNotNull(this.getOpenID())) {
            const me = this;
            wx.getUserInfo({
                withCredentials: false,
                success: function (res) {
                    me.setWechatUserInfo(res.userInfo)
                    if (JJUtil.isNotNull(me.getOpenID())) {
                        res.userInfo.openId = me.getOpenID()
                    }
                    if (JJUtil.isNotNull(me.getUnionID())) {
                        res.userInfo.unionId = me.getUnionID()
                    }
                    networkSuccessCallBack(true, res.userInfo, {})
                },
                fail: function (error) {
                    networkFailCallBack(JJError.networkReuqestFailError, {})
                },
            })

            return
        }
        
        if (JJUtil.isNotNull(this.getWechatUserInfo()) && JJUtil.isNotNull(this.getOpenID())) {
            let value = this.getWechatUserInfo()
            value.openId = this.getOpenID()
            if (JJUtil.isNotNull(me.getUnionID())) {
                value.unionId = me.getUnionID()
            }
            networkSuccessCallBack(true, value, {})
        } else {
            const me = this;
            this.__requestWechatLogin(function (isSuccess, value, otherInfo) {
                if (isSuccess) {
                    let withCredentials = true
                    if (JJUtil.isNotNull(me.getOpenID())) {
                        withCredentials = false
                    }

                    wx.getUserInfo({
                        withCredentials: withCredentials,
                        success: function (res) {
                            if (withCredentials) {
                                const params = { rawData: res.rawData, signature: res.signature, encryptedData: res.encryptedData, iv: res.iv, clientSessionKey: value.clientSessionKey }
                                JJService.request(JJLoginRequest, JJLoginService.JJLoginServiceIdentityGetWechatUserInfo, params, true, true, function (isSuccess, value, otherInfo) {
                                    if (isSuccess) {
                                        const userInfo = value.userInfoDec
                                        me.setOpenID(userInfo.openId)
                                        me.setUnionID(userInfo.unionId)
                                        me.setWechatUserInfo(userInfo)
                                        value = userInfo
                                    }
                                    networkSuccessCallBack(isSuccess, value, otherInfo)
                                }, networkFailCallBack)
                            } else {
                                me.setWechatUserInfo(res.userInfo)
                                networkSuccessCallBack(isSuccess, res.userInfo, otherInfo) 
                            }
                        },
                        fail: function (error) {
                            networkFailCallBack(JJError.networkReuqestFailError, {})
                        },
                    })
                } else {
                    networkSuccessCallBack(isSuccess, value, otherInfo)
                }
            }, networkFailCallBack)
        }
    }

    // 退出登录
    requestLogout(networkSuccessCallBack, networkFailCallBack) {
        // todo set parameter
        let parameter = {}
        
        const me = this
        JJService.request(JJLoginRequest, JJLoginService.JJLoginServiceIdentityLogout, parameter, true, false, function (isSuccess, value, otherInfo) {
            if (isSuccess) {
                me.setIsUserDidOnline(false)
                me.clear()
                
                WxNotificationCenter.postNotificationName(JJLoginService.JJLoginServiceNotificationNameLogoutSuccess, {})
            }
            
            networkSuccessCallBack(isSuccess, value, otherInfo)
        }, networkFailCallBack);
    }

    // 微信登录，不要单独调用此接口，在注册、密码登录、免密登录接口中调用
    __requestWechatLogin(networkSuccessCallBack, networkFailCallBack) {
        const me = this;
        wx.login({
            success: function (res) {
                if (res.code) {
                    const parameter = { code: res.code }
                    JJService.request(JJLoginRequest, JJLoginService.JJLoginServiceIdentityWechatLogin, parameter, true, false, (isSuccess, value, otherInfo) => {
                        if (isSuccess) {
                            me.setOpenID(value.openid)
                            me.setUnionID(value.unionid)
                            // todo maybe save other info
                        }
                        networkSuccessCallBack(isSuccess, value, otherInfo)
                    }, networkFailCallBack)
                } else {
                    networkFailCallBack(JJError.networkReuqestFailError, {})
                }
            },
            fail: function (res) {
                networkFailCallBack(JJError.networkReuqestFailError, {})
            },
        })
    }

    __beforeLoginAction() {
        let promise = new Promise(function (resolve, reject) {
            resolve({})
            // todo maybe do something before login
        });
        return promise;
    }

    // 登录
    __requestLogin(params, identity, networkSuccessCallBack, networkFailCallBack) {
        const me = this;
        this.__requestWechatLogin(function (isSuccess, value, otherInfo) {
            if (isSuccess) {
                me.__beforeLoginAction().then((value) => {
                    JJService.request(JJLoginRequest, identity, params, true, false, function (isSuccess, value, otherInfo) {
                        if (isSuccess) {
                            // todo save login info
                            me.setIsUserDidOnline(true)
                            me.setLoginInfo(value)
                            WxNotificationCenter.postNotificationName(JJLoginService.JJLoginServiceNotificationNameLoginSuccess, { identity, value, otherInfo})
                        }
                        networkSuccessCallBack(isSuccess, value, otherInfo)
                    }, networkFailCallBack)
                 }).catch((error) => {
                    networkFailCallBack(JJError.networkReuqestFailError, otherInfo)
                 })
            } else {
                networkSuccessCallBack(isSuccess, value, otherInfo)
            }
        }, networkFailCallBack)
    }
}
